package com.fingard.dsp.bank.directbank.dbs01;

import com.fingard.dsp.bank.directConfig.ListenerSet;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

import java.io.File;
import java.sql.Connection;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;
import java.util.UUID;

import com.fingard.FGBiz;
import com.fingard.constant.Format;
import com.fingard.db.JDBCHelper;
import com.fingard.dsp.bank.directbank.PaymentState;
import com.fingard.dsp.bank.directbank.bankInterface.ISinglePay;
import com.fingard.dsp.bank.reqrespobj.single.*;
import com.fingard.dsp.bank.reqrespobj.single.detail.RetAtsSglDetail;
import com.fingard.io.FileHelper;
import com.fingard.net.ConnState;
import com.fingard.text.StringHelper;

/**
 * Created by F on 2018/7/16.
 */
public class DBS01SinglePay extends DBS01Base implements ISinglePay {

    private static final String SELECTSEQ = "SELECT STATE,RESERVE1 FROM REQSEQIDMAPPING WHERE REQSEQID=?;";
    private static final String INSERTSEQ = "INSERT INTO REQSEQIDMAPPING(URID,BANKCODE,TRANSDATE,REQSEQID,STATE,RESERVE1) values (?,?,?,?,?,?);";

    public String getBatchId() throws Exception {
        String batchPath = getBankConfig().getValueAsString("BatchPath")+File.separator+"batch_id.txt";
        String batchId ;
        synchronized (DBS01SinglePay.class) {
            if (!FileHelper.existFile(batchPath)) {
                batchId = "00001";
                FileHelper.writeFile(batchPath, batchId, getCharset());
            } else {
                batchId = FileHelper.readFileText(batchPath, getCharset());
                int index = (Integer.valueOf(batchId) + 1) % 100000;
                batchId = String.format("%05d", index);
                FileHelper.writeFile(batchPath, batchId, getCharset());
            }
            return batchId;
        }
    }

    @Override
    public RetAtsSingle d_1908_SglPay(ReqSingle p_req1908) throws Exception {
        return "1".equals(getBankConfig().getValueAsString("channelFlag"))?d1908SglPayApi(p_req1908):d1908SglPayFile(p_req1908);
    }

    /**
     * api方式 付款
     * @param p_req1908
     * @return
     * @throws Exception
     */
    public RetAtsSingle d1908SglPayApi(ReqSingle p_req1908) throws Exception{
        RetAtsSingle retAts = new RetAtsSingle(p_req1908.reqHeader);
        RetAtsSglDetail detail = new RetAtsSglDetail();
        Connection conn= FGBiz.getLocalDbConn();
        try{
            String date=Format.DateTimeSSSFormat.format(new Date());//yyyy-MM-dd HH:mm:ss SSS
            StringBuilder sb2=new StringBuilder(date.replaceAll(" ",""));
            sb2.insert(10,"T").insert(19,".");

            JSONObject header = new JSONObject();
            header.put("msgId", p_req1908.singleDetail.askNumber);//流水号
            header.put("orgId", bankFront.org);//机构号
            header.put("timeStamp", sb2.toString());//时间 yyyy-MM-ddTHH:mm:ss.SSS
            header.put("ctry", getBankConfig().getMapKeyByValue("cityFlag",p_req1908.singleDetail.payAct));//Country triggering the JSON
            header.put("noOfTxs", "1");//Default to 1
            header.put("totalTxnAmount", p_req1908.singleDetail.payAmount);//交易金额
            JSONArray array=new JSONArray();//单笔支付
            JSONObject txnInfo = new JSONObject();
            txnInfo.put("customerReference", p_req1908.singleDetail.askNumber);//唯一标识
            if("1".equals(p_req1908.singleDetail.sameBnk)){//同行
                txnInfo.put("txnType", "ACT");//Transaction type. Book Transfers �C ACT
            }else if("0".equals(p_req1908.singleDetail.sameBnk)){//跨行
                txnInfo.put("txnType", "RTGS");//Transaction type. CNAPS Payments �C RTGS
            }
            txnInfo.put("txnDate", p_req1908.singleDetail.payDate);//交易日期
            txnInfo.put("txnCcy", convertCurToBank(p_req1908.singleDetail.payCur));//付方币种
            txnInfo.put("txnAmount", p_req1908.singleDetail.payAmount);//付方金额
            txnInfo.put("debitAccountCcy", convertCurToBank(p_req1908.singleDetail.payCur));//
            txnInfo.put("debitAccountAmount", "null");//
            if("1".equals(p_req1908.singleDetail.sameBnk)){
                txnInfo.put("fxContractRef1", "null");//
                txnInfo.put("fxAmountUtilized1", "null");//
                txnInfo.put("fxContractRef2", "null");//
                txnInfo.put("fxAmountUtilized2", "null");//
            }
            JSONObject senderParty=new JSONObject();
            senderParty.put("name",p_req1908.singleDetail.payName);//付方名字
            senderParty.put("accountNo",p_req1908.singleDetail.payAct);//付方账号
            senderParty.put("bankCtryCode",getBankConfig().getMapKeyByValue("cityFlag",p_req1908.singleDetail.payAct));//付方账户国家代码
            senderParty.put("swiftBic",getBankConfig().getValueAsString("paySwiftBic"));//付方swifiBic
            txnInfo.put("senderParty", senderParty);//发送方详细信息
            JSONObject receivingParty=new JSONObject();
            receivingParty.put("name",p_req1908.singleDetail.recName);
            receivingParty.put("accountNo",p_req1908.singleDetail.recAct);
            if("0".equals(p_req1908.singleDetail.sameBnk)){
                receivingParty.put("bankCtryCode",getBankConfig().getMapKeyByValue("cityFlag",p_req1908.singleDetail.recAct));//Bank country code
                receivingParty.put("clearingCode",p_req1908.singleDetail.cnapsCode);//联行号
                receivingParty.put("bankName",p_req1908.singleDetail.cnapsName);//银行名称
                receivingParty.put("bankAddress",StringHelper.isNullOrEmpty(p_req1908.singleDetail.recBankAddress)?"null":p_req1908.singleDetail.recBankAddress);//银行地址
                receivingParty.put("beneficiaryAddresses","null");//
                if("1".equals(p_req1908.singleDetail.paySpd)){
                    receivingParty.put("countrySpecific","02");//01 Normal 02 Urgent 03 Express
                }else if("0".equals(p_req1908.singleDetail.paySpd)){
                    receivingParty.put("countrySpecific","01");//01 Normal 02 Urgent 03 Express
                }
            }
            txnInfo.put("receivingParty", receivingParty);//收方信息
            JSONObject adviseDelivery=new JSONObject();
            adviseDelivery.put("mode","null");
            adviseDelivery.put("emails","null");
            adviseDelivery.put("phoneNumbers","null");
            txnInfo.put("adviseDelivery", adviseDelivery);//通知建议
            JSONObject rmtInf=new JSONObject();
            JSONArray paymentDetails2=new JSONArray();
            JSONObject paymentDetails=new JSONObject();
            paymentDetails.put("paymentDetails",p_req1908.singleDetail.purpose);
            paymentDetails2.add(paymentDetails);
            rmtInf.put("paymentDetails",paymentDetails2);//详情
            rmtInf.put("clientReferences","null");//附言
            rmtInf.put("invoiceDetails","null");
            txnInfo.put("rmtInf",rmtInf);
            JSONObject txnInfoDetails = new JSONObject();
            array.add(txnInfo);
            txnInfoDetails.put("txnInfo",array);
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("header",header);
            jsonObject.put("txnInfoDetails",txnInfoDetails);
            //发送请求报文
            String[] bankResult = sendToBank(jsonObject.toString(),"stpcn/v1/payment/initiatePayment");
            //处理响应报文
            if (bankResult[0].length() == 0) {
                JSONObject jsonArray = JSONObject.fromObject(bankResult[1].replaceAll(" ", "")
                        .replaceAll("\\[","").replaceAll("]",""));
                if (!"".equals(jsonArray.get("txnResponses")) && jsonArray.get("txnResponses") != null) {
                    JSONObject object=(JSONObject)jsonArray.get("txnResponses");
                    detail.respCode = "0";
                    detail.respInfo = object.get("txnStatusDescription").toString();
                    detail.reqSeqID = p_req1908.singleDetail.askNumber;
                    detail.transState = object.get("responseType").toString()+"+"+object.get("txnStatus").toString();
                    detail.payInfoCode = detail.transState;
                    detail.transAmt = "";//交易金额
                    detail.outTransID = "";
                    //记录付款状态
                    String uuid = UUID.randomUUID().toString().replaceAll("-", "");
                    JDBCHelper.update(conn, INSERTSEQ, new Object[]{uuid, bankFront.bankCode, Format.Date8Format.format(new Date()), p_req1908.singleDetail.askNumber, detail.transState,detail.respInfo});
                }
            }else if (bankResult[0].equals(ConnState.FAIL)) {
                detail.respCode = "0";
                detail.respInfo = bankResult[1];
                detail.reqSeqID = p_req1908.singleDetail.askNumber;
                detail.transState = PaymentState.FAIL_Payment;
                detail.payInfoCode = bankResult[0];
            } else{
                detail.respCode ="-1";
                detail.respInfo = bankResult[1];
            }
        }catch (Exception e){
            detail.respCode = "-1";
            detail.respInfo = e.getMessage();
            e.printStackTrace();
            WriteBankLogLn("转账出现异常:"+e);
        }finally {
            conn.close();
        }
        retAts.writeRetDetail(detail);
        return retAts;
    }

    /**
     * sftp文件方式 付款
     * @param p_req1908
     * @return
     * @throws Exception
     */
    public RetAtsSingle d1908SglPayFile(ReqSingle p_req1908) throws Exception{
        RetAtsSingle retAts = new RetAtsSingle(p_req1908.reqHeader);
        RetAtsSglDetail detail = new RetAtsSglDetail();
        StringBuilder content =new StringBuilder();
        Date date = new Date();
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("ddMMyyyy");
        String dateStr = simpleDateFormat.format(date);
        //HEADER,16012018,CNLM004,Test Account Name
        String batch_id = getBatchId();
        //由于收方有长度限制且银行不校验该值，写成固定值
        String payName = getBankConfig().getValueAsString("payName");
        String org = getBankConfig().getMapAdvanceValue("Organization","key","org",p_req1908.singleDetail.payAct);
        //HEADER,ddMMyyyy,网银机构代码，付款人名称
        content.append("HEADER,").append(dateStr+",").append(org+",").append(payName+"\r\n");
//        文件类型，付款类型，付款账号，账户币种  ，客户参考号，付款币种，批次号，交易日期，，，收款人名称，，，，，
//        收款人账号，是否加急，，，，，收款银行名称，，，，，，金额，，，，，20，，，附言,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
        content.append("PAYMENT,");//        文件类型，
        content.append("TTC,");//           付款类型
        content.append(p_req1908.singleDetail.payAct+",");//   付款账号
        String cur = convertCurToBank(p_req1908.singleDetail.payCur);
        String paydate =simpleDateFormat.format(Format.Date10Format.parse(p_req1908.singleDetail.payDate));
        content.append(cur+",");//账户币种
        content.append(p_req1908.singleDetail.askNumber+",");//客户参考号
        content.append(cur+",");//付款币种
        content.append(batch_id+",");//批次号
        content.append(paydate);//交易日期
        content.append(",,,");
        content.append(p_req1908.singleDetail.recName);//收款人名称
        content.append(",,,,,");
        content.append(p_req1908.singleDetail.recAct+",");//收款人账号
        String paySpd="";
        if("1".equals(p_req1908.singleDetail.paySpd)){
            paySpd="02";
        }else{
            paySpd="01";
        }
        content.append(paySpd);//是否加急
        content.append(",,,,,");
        content.append(p_req1908.singleDetail.recBankLocation);//收款人银行名称
        content.append(",,,,,,");
        content.append(p_req1908.singleDetail.payAmount);//金额
        content.append(",,,,,20,,,");//固定字段
        String postScript = p_req1908.singleDetail.purpose;
        if(postScript.length()>30){
            postScript =postScript.substring(0,30);
        }
        if(StringHelper.hasAnyChar(postScript)&&postScript.indexOf(",")!=-1){
            postScript = "\""+postScript+"\"";
        }
        //附言，长度不超过30
        content.append(postScript+",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,\r\n");
        //RAILER,交易总笔数，交易总金额
        content.append("TRAILER,1,"+p_req1908.singleDetail.payAmount);
        String transTime = Format.Date8Format.format(Format.DateTimeFormat.parse(p_req1908.reqHeader.transTime));
        //生成支付文件
        String supOrg =getBankConfig().getMapAdvanceValue("Organization","key","supOrg",p_req1908.singleDetail.payAct);
        //UFF1.STP.CNLM004.CNLM004.TTC20180116001.txt.DBSSCNSH
        String paydate2 = p_req1908.singleDetail.payDate.replaceAll("-","");
        String fullName =getBankConfig().getValueAsString("PayFilePath")+ File.separator+paydate2+File.separator+
                "UFF1.STP."+supOrg+"."+org+"."+transTime+"TTC"+p_req1908.singleDetail.askNumber +".txt.DBSSCNSH";
        if(!exportContentToFile(content.toString(),fullName)){
            detail.respCode="0";
            detail.respInfo = "生成支付文件失败";
            detail.transState = "E1101";
            detail.payInfoCode = "E1101";
            retAts.writeRetDetail(detail);
            return retAts;
        }
        //对支付文件加密，并生成加密文件
        if(!encrypFile(fullName)){
            detail.respCode="0";
            detail.respInfo = "生成加密文件失败";
            detail.transState="E1102";
            detail.transState="E1102";
            retAts.writeRetDetail(detail);
            return retAts;
        }
        //上传文件
        fullName = fullName+".pgp";
        if(!uploadFile(fullName)){
            detail.respCode = "0";
            detail.respInfo="上传文件失败";
            detail.transState = "E1103";
            detail.payInfoCode ="E1103";
            retAts.writeRetDetail(detail);
            return retAts;
        }
        detail.respCode = "0";
        detail.respInfo = "发送文件成功";
        detail.transState = "Vaild";
        detail.payInfoCode = "Vaild";
        retAts.writeRetDetail(detail);
        return retAts;
    }

    /**
     * api方式 付款状态查询
     * @param p_req1944
     * @return
     * @throws Exception
     */
    public RetAtsSingle d1944QrySglPayApi(ReqQrySingle p_req1944) throws Exception{
        RetAtsSingle retAts = new RetAtsSingle(p_req1944.reqHeader);
        RetAtsSglDetail detail = new RetAtsSglDetail();
        //存在侦听，使用银行主动推送的方式
        ListenerSet eachSet=null;
        if(bankFront.hashListenerSet!=null){
            eachSet = bankFront.hashListenerSet.get("");
        }
        if(eachSet!=null && "true".equals(eachSet.enable)){
            Connection conn= FGBiz.getLocalDbConn();
            try{
                //查询返回的付款状态
                Map<String, Object> selMap=JDBCHelper.execQuerySingle(conn,SELECTSEQ,new Object[]{p_req1944.askNumber});
                if(selMap.size()>0){
                    WriteBankLogLn("流水号"+p_req1944.askNumber+"查询到付款状态"+selMap.get("STATE").toString()+"；付款描述"+selMap.get("RESERVE1").toString());
                    detail.respCode = "0";//响应码
                    detail.respInfo = selMap.get("RESERVE1").toString();//响应结果
                    detail.reqSeqID = p_req1944.askNumber;//交易流水号
                    detail.transState = selMap.get("STATE").toString();//状态
                    detail.payInfoCode = detail.transState;
                }else {
                    WriteBankLogLn("流水号"+p_req1944.askNumber+"未查询到付款状态");
                    detail.respCode = "-1";//响应码
                    detail.respInfo = "流水号"+p_req1944.askNumber+"未查询到付款状态";//响应结果
                }
            }catch (Exception e){
                detail.respCode = "-1";
                detail.respInfo = e.getMessage();
                e.printStackTrace();
                WriteBankLogLn("api方式查询付款状态异常："+e);
            }finally {
                conn.close();
            }
        }else {
            //不存在侦听，使用调用银行接口的方式
            String date=Format.DateTimeSSSFormat.format(new Date());//yyyy-MM-dd HH:mm:ss SSS
            StringBuilder sb2=new StringBuilder(date.replaceAll(" ",""));
            sb2.insert(10,"T").insert(19,".");
            JSONObject header = new JSONObject();
            header.put("msgId", p_req1944.reqHeader.transSeqID);//流水号
            header.put("orgId", bankFront.org);//机构号
            header.put("timeStamp", sb2.toString());//时间 yyyy-MM-ddTHH:mm:ss.SSS
            header.put("ctry", getBankConfig().getMapKeyByValue("cityFlag",p_req1944.payAct));//Country triggering the JSON
            JSONObject txnInfo = new JSONObject();
            txnInfo.put("txnType", " TSE");//Transaction type
            txnInfo.put("enqType", "REM");//Enquiry Type  RET for Real-time Transaction Enquiry   REM for Remittance Transaction Enquiry
            JSONObject txnEnquiry = new JSONObject();
            txnEnquiry.put("enqAccountNo",p_req1944.payAct);//账号
            txnEnquiry.put("vpa","");//
            txnEnquiry.put("customerReference",p_req1944.askNumber);//唯一支付流水号
            txnEnquiry.put("txnRefId","");
            txnEnquiry.put("refId","");
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("header",header);
            jsonObject.put("txnInfo",txnInfo);
            jsonObject.put("txnEnquiry",txnEnquiry);
            //发送请求报文
            String[] bankResult = sendToBank(jsonObject.toString(),"enquiry/v1/transaction/status");
            //测试
            //String[] bankResult=new String[]{"","{\"header\":{\"msgId\":\"TSE170211SGLVABC440\",\"orgId\":\"ABC123\",\"timeStamp\":\"2017-06-30T08:37:52.756\"},\"txnEnqResponse\":{\"enqType\":\"REM\",\"enqStatus\":\"ACSP\",\"customerReference\":\"TLV20170521INABC440DBSTxnId440\",\"customerTxnId\":\"\",\"msgRefId\":\"IRS1706300000001\",\"txnRefId\":\"RAS1706300000001\",\"bankReference\":\"ACT2009201700012\",\"refId\":\"\",\"txnType\":\"ACT\",\"txnStatus\":\"ACTC\",\"txnRejectCode\":\"\",\"txnStatusDescription\":\"Success\",\"txnCcy\":\"SGD\",\"txnAmount\":\"234.56\",\"debitAccountCcy\":\"SGD\",\"txnSettlementAmt\":\"234.56\",\"txnSettlementDt\":\"2017-06-30\",\"clientReferences\":[{\"clientReference\":\"TSE170211SGLVABC440ClientReference1\"},{\"clientReference\":\"clientReference2\"}],\"fxContractRef1\":\"str1234\",\"fxAmountUtilized1\":\"0.00\",\"fxContractRef2\":\"str12345\",\"fxAmountUtilized2\":\"0.00\",\"chargeBearer\":\"CRED\",\"debitAccountForBankCharges\":\"0039156414\",\"chargesCcy\":\"SGD\",\"chargesAmount\":\"2.345\",\"senderParty\":{\"name\":\"GTSSGDAccountCompanyName1\"},\"receivingParty\":{\"name\":\"SGBeneficiary-SGDAccount\",\"accountNo\":\"02084784143\",\"bankCtryCode\":\"SG\",\"swiftBic\":\"SCBLSGS0XXX\",\"bankName\":\"Bank1\",\"beneficiaryAddresses\":[{\"address\":\"address1\"},{\"address\":\"address2\"},{\"address3\":\"address3\"}]}}}"};
            //处理响应报文
            if (bankResult[0].length() == 0) {
                JSONObject jsonArray = JSONObject.fromObject(bankResult[1].replaceAll(" ", ""));
                if (!"".equals(jsonArray.get("txnEnqResponse")) && jsonArray.get("txnEnqResponse") != null) {
                    JSONObject object=(JSONObject)jsonArray.get("txnEnqResponse");
                    if("ACSP".equals(object.get("enqStatus").toString())){
                        detail.respCode = "0";//响应码
                        detail.respInfo = object.get("txnRejectCode").toString()+object.get("txnStatusDescription").toString();//响应结果
                        detail.reqSeqID = p_req1944.askNumber;//交易流水号
                        String txnStatusDescription=object.get("txnStatusDescription").toString().toLowerCase();
                        if(txnStatusDescription.contains("ack3")){
                            detail.transState = "ack3+"+object.get("txnStatus").toString();//状态
                        }else {
                            detail.transState = object.get("txnStatus").toString();//状态
                        }
                        detail.payInfoCode = detail.transState;
                    }else if("RJCT".equals(object.get("enqStatus").toString())){
                        detail.respCode ="-1";
                        detail.respInfo = object.get("enqRejectCode").toString()+object.get("enqStatusDescription").toString();
                    }else {
                        detail.respCode ="-1";
                        detail.respInfo = "响应状态异常："+object.get("enqStatus").toString();
                    }
                }else{
                    detail.respCode ="-1";
                    detail.respInfo = bankResult[1];
                }
            } else{
                detail.respCode ="-1";
                detail.respInfo = bankResult[1];
            }
        }
        retAts.writeRetDetail(detail);
        return retAts;
    }

    /**
     * sftp文件方式 付款状态查询
     * @param p_req1944
     * @return
     * @throws Exception
     */
    public RetAtsSingle d1944QrySglPayFile(ReqQrySingle p_req1944) throws Exception{
        RetAtsSingle retAts = new RetAtsSingle(p_req1944.reqHeader);
        RetAtsSglDetail detail = new RetAtsSglDetail();
        String dealedPath = getBankConfig().getValueAsString("DealedPath");
        String fullname = dealedPath+File.separator+Format.Date8Format.format(Format.DateTimeFormat.parse(p_req1944.bgnDate))
                + File.separator+"ACK"+File.separator+p_req1944.askNumber+".txt";
//        if(FileHelper.existFile(fullname)){
//            //流水号|状态|更新日期
//            String fileContent = FileHelper.readFileText(fullname,getCharset());
//            String[] filesplit = fileContent.split("\\|");
//            detail.respCode = "0";
//            detail.reqSeqID = filesplit[0];
//            detail.transState =filesplit[1];
//            detail.payInfoCode = filesplit[1];
//            retAts.writeRetDetail(detail);
//            return retAts;
//        }
//        else {
//            synchronized (DBS01Base.class) {
//                List<String> fileList = downloadFile();
//
//                for (String filename : fileList) {
//                    decryptFile(filename);
//                }
//                if (fileList == null || fileList.size() == 0) {
//                    String receiveFilePath = getBankConfig().getValueAsString("ReceiveFilePath");
//                    for (String fileName : new File(receiveFilePath).list()) {
//                        boolean success = false;
//                        success = decryptFile(fileName);
//                        if (success) {
//                            //统计解密成功的文件
//                            fileList.add(fileName);
//                        }
//                    }
//
//                }
//                for (String filename : fileList) {
//                    analysisFile(filename);
//                }
//            }
//        }
        if(FileHelper.existFile(fullname)){
            String fileContent = FileHelper.readFileText(fullname,getCharset());
            //流水号|状态|更新日期
            String[] fileSplit = fileContent.split("\\|");
            detail.respCode = "0";
            detail.reqSeqID = fileSplit[0];
            detail.transState =fileSplit[1];
            detail.payInfoCode = fileSplit[1];
        }else{
            detail.respCode = "-1";
            detail.respInfo = "找不到该支付记录";
        }
        retAts.writeRetDetail(detail);
        return retAts;
    }

    @Override
    public RetAtsSingle d_1944_QrySglPay(ReqQrySingle p_req1944) throws Exception {
        return "1".equals(getBankConfig().getValueAsString("channelFlag"))?d1944QrySglPayApi(p_req1944):d1944QrySglPayFile(p_req1944);
    }

    @Override
    public RetAtsSingleBat d_1908BAT_SglBatPay(ReqSingleBat p_req1908BAT) throws Exception {
        return null;
    }

    @Override
    public RetAtsSingleBat d_1944BAT_QrySglBatPay(ReqQrySingleBat p_req1944BAT) throws Exception {
        return null;
    }
}